package com.eis.persist.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.eis.admin.mvc.bean.BizGroupBean;
import com.eis.admin.mvc.bean.FunctionBean;
import com.eis.exception.EisErrorCode;
import com.eis.exception.EisSysException;
import com.eis.persist.dao.UserDAO;
import com.eis.persist.dao.UserFunctionDAO;
import com.eis.persist.dao.base.BaseDAO;
import com.eis.persist.dao.util.Constants;
import com.eis.persist.dao.util.DeleteGroupFunctionBatchSetter;
import com.eis.persist.dao.util.FunctionParameterBatchSetter;
import com.eis.persist.dao.util.GroupFunctionBatchSetter;
import com.eis.persist.model.function.PersistFunction;
import com.eis.persist.model.function.PersistFunctionDestInvokeInfo;
import com.eis.persist.model.function.PersistFunctionLayoutGroup;
import com.eis.persist.model.function.PersistFunctionParameter;
import com.eis.persist.model.function.PersistFunctionType;

public class UserFunctionDAOImpl extends BaseDAO implements UserFunctionDAO {
	private static final Logger logger = LoggerFactory.getLogger(UserFunctionDAOImpl.class);
	
	public UserFunctionDAOImpl(JdbcTemplate dataSource) {
		
		super(dataSource);
	}
	
	public UserFunctionDAOImpl(JdbcTemplate dataSource, String currentUserName) {
		super(dataSource, currentUserName);
	}

	@Override
	public List<FunctionBean> getFunctionsForList(int userBizGroupId,
			int pageCount, int pageRows, FunctionBean functionFilter) {
		StringBuilder loadFunctionSql = new StringBuilder("select func.*,typee.typeName,typee.DisplayName,typee.description,bizsys.name as bizsysName,connconf.name as configName ");
		loadFunctionSql.append("from tb_function func ");
		loadFunctionSql.append("inner join tb_function_type typee on func.typeId=typee.id ");
		loadFunctionSql.append("inner join tb_biz_system bizsys on func.bizsysId=bizsys.id ");
		loadFunctionSql.append("inner join tb_bizgroupfunction groupFunction on func.functionID=groupFunction.functionid ");
		loadFunctionSql.append("left join tb_connector_config connconf on func.bizsysConnectorConfig=connconf.id ");
		loadFunctionSql.append("where groupFunction.bizGroupId=? ");
		if (functionFilter != null && functionFilter.isFilterable()) {
			if (functionFilter.getFunctionID() != null && functionFilter.getFunctionID().trim().length() > 0)  {
				loadFunctionSql.append("and func.functionID like '%" + functionFilter.getFunctionID() + "%' ");
			}
			if (functionFilter.getFunctionName() != null && functionFilter.getFunctionName().trim().length() > 0) {
				loadFunctionSql.append("and func.functionDisplayName like '%" + functionFilter.getFunctionName() + "%' ");
			}
			
			if (functionFilter.getStatus() >=0) {
				loadFunctionSql.append("and func.isActive=" + functionFilter.getStatus() + " ");
			}
			
			if (functionFilter.getTypeId() > 0) {
				loadFunctionSql.append("and func.typeId=" + functionFilter.getTypeId() + " ");
			} 
		}
		loadFunctionSql.append(" order by func.functionID");
		
		// get customized group id
		UserDAO userdao = new UserDAOImpl(dataSource);
		List<BizGroupBean> allGroups = userdao.getAllBizGroups();
		for (BizGroupBean oneBean : allGroups) {
			if (oneBean.getId() == userBizGroupId) {
				if (oneBean.getCustomized() > 0) {
					// get customized functions
					List<Map<String, Object>> customizedFunctions = dataSource.queryForList(loadFunctionSql.toString(), userBizGroupId);
					List<FunctionBean> returnFunctions = new ArrayList<FunctionBean>();
					for (Map<String, Object> oneFunction : customizedFunctions) {
						PersistFunction pf = new PersistFunction(oneFunction);
						returnFunctions.add(new FunctionBean(pf));
					}
					return returnFunctions; 
				} else {
					// get parent functions
					int queryGroupId = oneBean.getCustomizedParentId();
					List<Map<String, Object>> parentFunctions = dataSource.queryForList(loadFunctionSql.toString(), queryGroupId);
					
					List<FunctionBean> returnFunctions = new ArrayList<FunctionBean>();
					for (Map<String, Object> oneFunction : parentFunctions) {
						returnFunctions.add(new FunctionBean(new PersistFunction(oneFunction)));
					}
					
					return returnFunctions; 
				}
			}
		}
		
		return  new ArrayList<FunctionBean>();
	}

	@Override
	public List<PersistFunctionType> getFunctionTypes() {
		String sql = "select * from tb_function_type";
		List<Map<String, Object>> functionTypes = dataSource.queryForList(sql);
		
		List<PersistFunctionType> returnList = new ArrayList<PersistFunctionType>();
		for (Map<String, Object> functionType : functionTypes) {
			PersistFunctionType type = new PersistFunctionType((Integer)functionType.get("id"), 
					(String) functionType.get("typeName"),
					(String) functionType.get("DisplayName"),
					(String) functionType.get("description"));
			
			returnList.add(type);
		}
		return returnList;
	}

	@Override
	public boolean disableOrEnableFunctionById(int functionId, boolean active) {
		int count = dataSource.update("update tb_function set isActive=" + (active? 1 : 0) +
				" where id=?", functionId);
		
		return count > 0;
	}

	@Override
	public List<PersistFunctionLayoutGroup> getFunctionLayoutGroups(int bizsysId) {
		String sql = "select * from tb_layoutgroup where bizsysId=?";
		List<Map<String, Object>> layoutGroups = dataSource.queryForList(sql, bizsysId);
		
		List<PersistFunctionLayoutGroup> returnList = new ArrayList<PersistFunctionLayoutGroup>();
		for (Map<String, Object> onelayoutGroup : layoutGroups) {
			PersistFunctionLayoutGroup layoutGroup = new PersistFunctionLayoutGroup(onelayoutGroup);
			
			if (Constants.DEFAULT_GROUP_NAME.equals(layoutGroup.getDefaultDisplayName())) {
				returnList.add(0, layoutGroup);
			} else {
				returnList.add(layoutGroup);
			}
			
		}
		return returnList;
	}

	@Override
	@Transactional
	public boolean createFunction(FunctionBean functionData) {
		// create function first
		StringBuilder createFunctionSql = new StringBuilder("insert into tb_function(");
		createFunctionSql.append("functionID, typeId, functionDisplayName, isActive, datafetchID, bizsysId, lastDataFetchTime, createDate, data_unique_key, bizsysConnectorConfig, createBy");
		createFunctionSql.append(") values (");
		createFunctionSql.append("?,?,?,1,?,?,?,current_timestamp,?,?,?");
		// '1998-01-01 00:00:00'
		createFunctionSql.append(")");
		// save to DB
		int count = this.dataSource.update(createFunctionSql.toString(), functionData.getFunctionID(), functionData.getTypeId(), functionData.getFunctionName(), 
				functionData.getDatafetchID(), functionData.getBizsysId(), functionData.getLastFetchDate(), functionData.getDataUniqueKey(), functionData.getConnectorConfigId(), this.currentUserName);
		if (count > 0) {
			// quick actioner class
			String qacsql = "insert into tb_functionDestInvokeInfo(functionId, clientLibraryFileName, clientClassName, connectorLibraryFileName, connectorClassName, createDate, createBy) " +
					"values (?, ?, ?, ?, ?, current_timestamp, ?);";
			this.dataSource.update(qacsql, 
					functionData.getFunctionID(), 
					functionData.getClientLibraryFileName(),
					functionData.getClientClassName(),
					functionData.getConnectorLibraryFileName(),
					functionData.getConnectorClassName(),
					this.currentUserName);
			
			// function layout
			String losql = "insert into tb_functionLayout(defaultDisplayname, customizedDisplayName, layoutGroupId, createDate, createBy)";
			losql = losql + " values (?,?,?,current_timestamp,?)";
			this.dataSource.update(losql, functionData.getLayoutDefaultName(), null, functionData.getLayoutGroupId(), this.currentUserName);
			
			// biz group
			StringBuilder bizGroupFunctionSql = new StringBuilder("insert into tb_bizGroupFunction(functionId, bizGroupId, functionLayout, createDate, createBy)");
			bizGroupFunctionSql.append(" values (?,");
			bizGroupFunctionSql.append("(select id from tb_bizGroup where name=? order by id asc limit 1),");
			bizGroupFunctionSql.append("(select id from tb_functionLayout where defaultDisplayname=? and layoutGroupId=? order by id desc limit 1),");
			bizGroupFunctionSql.append("CURRENT_TIMESTAMP,");
			bizGroupFunctionSql.append("?)");
			
			int result = this.dataSource.update(bizGroupFunctionSql.toString(), functionData.getFunctionID(), Constants.DEFAULT_GROUP_NAME, functionData.getLayoutDefaultName(),
					functionData.getLayoutGroupId(), this.currentUserName);
			return result > 0;
		}
		
		return false;
	}

	@Override
	public FunctionBean getFunctionforEdit(String functionId) {
		String loadFunctionSql 
			= "select func.*,bizsys.name as bizsysName,bizsys.connectorStaticsClassName " +
					"from tb_function func " +
					"inner join tb_biz_system bizsys on func.bizsysId=bizsys.id " +
					"where functionId=?";
		List<Map<String, Object>> functionList = this.dataSource.queryForList(loadFunctionSql, functionId);
		
		if (functionList != null && functionList.size() > 0) {
			PersistFunction persistFunction = new PersistFunction(functionList.get(0));
			FunctionBean returnValue = new FunctionBean(persistFunction);
			
			// quick actioner
			String qacsql = "select * from tb_functionDestInvokeInfo where functionId=?";
			List<Map<String, Object>> quickActioner = this.dataSource.queryForList(qacsql, functionId);
			if (quickActioner != null && quickActioner.size() > 0) {
				Map<String, Object> settings = quickActioner.get(0);
				PersistFunctionDestInvokeInfo invkeInfo = new PersistFunctionDestInvokeInfo(settings);
				returnValue.setClientLibraryFileName(invkeInfo.getClientLibraryFileName());
				returnValue.setClientClassName(invkeInfo.getClientClassName());
				returnValue.setConnectorLibraryFileName(invkeInfo.getConnectorLibraryFileName());
				returnValue.setConnectorClassName(invkeInfo.getConnectorClassName());
			}
			
			// layout
			String layoutSql = "select defaultDisplayname, customizedDisplayName, layoutGroupId " +
					"from tb_bizGroupFunction bgf inner join tb_functionLayout flayout on bgf.functionLayout=flayout.id " +
					"where bgf.functionId=? and bgf.bizGroupId=(select id from tb_bizGroup where name=? order by id asc limit 1)";
			List<Map<String, Object>> layout = this.dataSource.queryForList(layoutSql, functionId, Constants.DEFAULT_GROUP_NAME);
			if (layout != null && layout.size() > 0) {
				Map<String, Object> layoutData = layout.get(0);
				
				String defaultName = (String) layoutData.get("defaultDisplayname");
				String customizeName = (String) layoutData.get("customizedDisplayName");
				int layoutGroupId = (Integer) layoutData.get("layoutGroupId");
				
				returnValue.setLayoutDefaultName((customizeName == null || customizeName.trim().length() == 0) ? defaultName : customizeName);
				returnValue.setLayoutGroupId(layoutGroupId);
			}
			
			
			return returnValue;
		}
		
		return null;
	}

	@Override
	public boolean editFunction(FunctionBean functionData) {
		// edit function first
		StringBuilder editFunctionSql = new StringBuilder("update tb_function set ");
		editFunctionSql.append("typeId=?,");
		editFunctionSql.append("functionDisplayName=?,");
		editFunctionSql.append("datafetchID=?,");
		editFunctionSql.append("data_unique_key=?,");
		editFunctionSql.append("bizsysConnectorConfig=?,");
		editFunctionSql.append("lastDataFetchTime=?,");
		editFunctionSql.append("updatedBy=?");
		editFunctionSql.append(" where functionID=?");
		
		// save to DB
		int count = 0;
		if (functionData.getConnectorConfigId() > 0) {
			count = this.dataSource.update(editFunctionSql.toString(),
					functionData.getTypeId(),
					functionData.getFunctionName(), functionData.getDatafetchID(),
					functionData.getDataUniqueKey(),
					functionData.getConnectorConfigId(), 
					functionData.getLastFetchDate(),
					this.currentUserName, functionData.getFunctionID());
		} else {
			count = this.dataSource.update(editFunctionSql.toString(),
					functionData.getTypeId(),
					functionData.getFunctionName(), functionData.getDatafetchID(),
					functionData.getDataUniqueKey(),
					null, 
					functionData.getLastFetchDate(),
					this.currentUserName, functionData.getFunctionID());
		}
		
		if (count > 0) {
			// quick actioner class
			String qacsql = "update tb_functionDestInvokeInfo set " +
					"clientLibraryFileName=?," +
					"clientClassName=?," +
					"connectorLibraryFileName=?," +
					"connectorClassName=? where functionId=?";
			
			int result = this.dataSource.update(qacsql, 
					functionData.getClientLibraryFileName(),
					functionData.getClientClassName(),
					functionData.getConnectorLibraryFileName(),
					functionData.getConnectorClassName(),
					functionData.getFunctionID());
			
			// function layout
			String losql = "update tb_functionLayout set customizedDisplayName=?, layoutGroupId=?, updatedBy=? where id=";
			losql = losql + "(select functionLayout from tb_bizGroupFunction where functionId=? and bizGroupId=(select id from tb_bizGroup where name=? order by id asc limit 1) order by id desc limit 1)";

			this.dataSource
					.update(losql, functionData.getLayoutDefaultName(), functionData.getLayoutGroupId(), this.currentUserName,
							functionData.getFunctionID(), Constants.DEFAULT_GROUP_NAME
							);
			return result > 0;
		}

		return false;
	}

	@Override
	public List<FunctionBean> getFunctionsForBizgroupAssign(int userGroupId, int targetGroupId,
			FunctionBean functionFilter) {
		UserDAO userdao = new UserDAOImpl(dataSource);		
		
		List<BizGroupBean> allGroups = userdao.getAllBizGroups();
		// check if the user can visit this group
		List<Integer> childrenIds = new ArrayList<Integer>();
		childrenIds.add(userGroupId);
		getAllChildren(childrenIds, allGroups, userGroupId);
		if (!childrenIds.contains(targetGroupId)) {
			return null;
		}
		
		StringBuilder loadFunctionSql = new StringBuilder("select func.*,typee.typeName,typee.DisplayName,typee.description,bizsys.name as bizsysName,connconf.name as configName ");
		loadFunctionSql.append("from tb_function func ");
		loadFunctionSql.append("inner join tb_function_type typee on func.typeId=typee.id ");
		loadFunctionSql.append("inner join tb_biz_system bizsys on func.bizsysId=bizsys.id ");
		loadFunctionSql.append("inner join tb_bizgroupfunction groupFunction on func.functionID=groupFunction.functionid ");
		loadFunctionSql.append("left join tb_connector_config connconf on func.bizsysConnectorConfig=connconf.id ");
		loadFunctionSql.append("where groupFunction.bizGroupId=? ");
		if (functionFilter != null && functionFilter.isFilterable()) {
			if (functionFilter.getFunctionID() != null && functionFilter.getFunctionID().trim().length() > 0)  {
				loadFunctionSql.append("and func.functionID like '%" + functionFilter.getFunctionID() + "%' ");
			}
			if (functionFilter.getFunctionName() != null && functionFilter.getFunctionName().trim().length() > 0) {
				loadFunctionSql.append("and func.functionDisplayName like '%" + functionFilter.getFunctionName() + "%' ");
			}
			
			if (functionFilter.getStatus() >=0) {
				loadFunctionSql.append("and func.isActive=" + functionFilter.getStatus() + " ");
			}
			
			if (functionFilter.getTypeId() > 0) {
				loadFunctionSql.append("and func.typeId=" + functionFilter.getTypeId() + " ");
			} 
		}
		loadFunctionSql.append(" order by func.functionID");
		
		// get customized group id
		for (BizGroupBean oneBean : allGroups) {
			if (oneBean.getId() == targetGroupId) {
				// get parent functions
				int queryGroupId = oneBean.getCustomizedParentId();
				if (queryGroupId <= 0) {
					queryGroupId = oneBean.getId();
				}
				List<Map<String, Object>> parentFunctions = dataSource.queryForList(loadFunctionSql.toString(), queryGroupId);
				
				if (oneBean.getCustomized() > 0) {
					// get customized function IDs
					StringBuilder loadCustimizedSql = new StringBuilder("select func.id ");
					loadCustimizedSql.append("from tb_function func ");
					loadCustimizedSql.append("inner join tb_bizgroupfunction groupFunction on func.functionID=groupFunction.functionid ");
					loadCustimizedSql.append("where groupFunction.bizGroupId=? ");
					List<Map<String, Object>> customizedFunctions = dataSource.queryForList(loadCustimizedSql.toString(), targetGroupId);
					
					Set<Integer> customizedFunctionIdSet = new HashSet<Integer>();
					for (Map<String, Object> oneFunctionId : customizedFunctions) {
						customizedFunctionIdSet.add((Integer) oneFunctionId.get("id"));
					}
					
					List<FunctionBean> returnFunctions = new ArrayList<FunctionBean>();
					for (Map<String, Object> oneFunction : parentFunctions) {
						PersistFunction pf = new PersistFunction(oneFunction);
						FunctionBean fb = new FunctionBean(pf);
						fb.setRemoved(customizedFunctionIdSet.contains(fb.getId()) ? 0 : 1);
						returnFunctions.add(fb);
					}
					return returnFunctions; 
				} else {
					List<FunctionBean> returnFunctions = new ArrayList<FunctionBean>();
					for (Map<String, Object> oneFunction : parentFunctions) {
						returnFunctions.add(new FunctionBean(new PersistFunction(oneFunction)));
					}
					
					return returnFunctions; 
				}
			}
		}
		
		return  new ArrayList<FunctionBean>();
	}

	@Override
	public boolean assignFunction(int bizGroupId, String functionId) {
		// check if the parent have this function
		UserDAO userdao = new UserDAOImpl(dataSource);
		List<BizGroupBean> allGroups = userdao.getAllBizGroups();
		
		for (BizGroupBean oneBean : allGroups) {
			if (oneBean.getId() == bizGroupId) {
				String countSql = "select count(id) from tb_bizGroupFunction where bizGroupId=? and functionID like ?";
				int count = super.dataSource.queryForInt(countSql, oneBean.getCustomizedParentId(), functionId);
				
				if (count > 0) {
					// have, just move on
					int count2 = super.dataSource.queryForInt(countSql, bizGroupId, functionId);
					
					if (count2 == 0) {
						String getLayoutSql = "select functionLayout from tb_bizGroupFunction where bizGroupId=? and functionID like ?";
						Map<String, Object> layoutResult = super.dataSource.queryForMap(getLayoutSql, oneBean.getCustomizedParentId(), functionId);
						
						String insertSql = "insert into tb_bizGroupFunction(functionID, bizGroupId, functionLayout, createDate, createBy) values (?,?,?,current_timestamp,?)";
						
						super.dataSource.update(insertSql, functionId, bizGroupId, (Integer)layoutResult.get("functionLayout"), super.currentUserName);
						
						String updateSql = "update tb_bizGroup set isConfiged=1, updateDate=current_timestamp, updatedBy=? where id=?";
						
						super.dataSource.update(updateSql, super.currentUserName, bizGroupId);
						
						return true;
					}
				}
			}
		}

		return false;
	}

	@Override
	public boolean removeFunction(int bizGroupId, String functionId) {
		// check if the parent have this function
		UserDAO userdao = new UserDAOImpl(dataSource);
		List<BizGroupBean> allGroups = userdao.getAllBizGroups();
		
		for (BizGroupBean oneBean : allGroups) {
			if (oneBean.getId() == bizGroupId) {
				if (oneBean.getCustomized() == 0) {
					// assign all parent function to this group
					String loadParentIdSql = "select functionID,functionLayout from tb_bizGroupFunction where bizGroupId=?";
					List<Map<String, Object>> result = super.dataSource.queryForList(loadParentIdSql, oneBean.getCustomizedParentId());
					
					List<String> functionIds = new ArrayList<String>();
					List<Integer> functionLayouts = new ArrayList<Integer>();
					for (Map<String, Object> oneId : result) {
						functionIds.add((String)oneId.get("functionID"));
						functionLayouts.add((Integer)oneId.get("functionLayout"));
					}
					
					GroupFunctionBatchSetter dataSetter = new GroupFunctionBatchSetter(functionIds, functionLayouts, bizGroupId, super.currentUserName);
					String insertSql = "insert into tb_bizGroupFunction(functionID, bizGroupId, functionLayout, createDate, createBy) values (?,?,?,current_timestamp,?)";
					
					super.dataSource.batchUpdate(insertSql, dataSetter);
					
					String updateSql = "update tb_bizGroup set isConfiged=1, updateDate=current_timestamp, updatedBy=? where id=?";
					
					super.dataSource.update(updateSql, super.currentUserName, bizGroupId);
				}

					// look for configured children
					List<Integer> childrenIds = new ArrayList<Integer>();
					childrenIds.add(bizGroupId);
					getAllChildren(childrenIds, allGroups, oneBean.getId());
					DeleteGroupFunctionBatchSetter setter = new DeleteGroupFunctionBatchSetter(childrenIds, functionId);
					String deleteUserPreferFunctionSql = "delete from tb_userPreferFunction where " +
							"bizGroupFunction in (select id from tb_bizGroupFunction where bizGroupId=? and functionID like ?)";
					super.dataSource.batchUpdate(deleteUserPreferFunctionSql, setter);
					
					String deletebizGroupFunctionSql = "delete from tb_bizGroupFunction where bizGroupId=? and functionID like ?";
					
					boolean updateResult = 
					super.dataSource.batchUpdate(deletebizGroupFunctionSql, setter).length > 0;
					
					return updateResult;
				}
			}
		return false;
	}
	
	public void getAllChildren(List<Integer> returnList, List<BizGroupBean> allGroups, int parentGroupId) {
		for (BizGroupBean oneGroup : allGroups) {
			if (oneGroup.getParentId() == parentGroupId) {
				returnList.add(oneGroup.getId());
				getAllChildren(returnList, allGroups, oneGroup.getId());
			}
		}
	}

	@Override
	public boolean addFunctionLayoutGroup(PersistFunctionLayoutGroup group) throws EisSysException {
		String sql = "insert into tb_layoutGroup (defaultDisplayname,customizedDisplayName,description,bizsysId,createDate,createBy) " +
				"values (?,?,?,?,current_timestamp,?)";
		try {
			return super.dataSource.update(
					sql, 
					group.getDefaultDisplayName(), 
					group.getDefaultDisplayName(), 
					group.getDescription(), 
					group.getBizsysId(),
					super.currentUserName) > 0;
		} catch (Throwable t) {
			EisSysException e = new EisSysException(EisErrorCode.InsertLayoutGroupFaile);
			logger.error("Exception when insert Layout Group: ", t);
			throw e;
		}
	}

	@Override
	public List<PersistFunctionParameter> getFunctionPramaters(int functionDBId) {
		List<PersistFunctionParameter> parameters = new ArrayList<PersistFunctionParameter>();
		String sql = "select para.* from tb_function func inner join tb_functionparameter para on func.id=para.functionDBID" +
				" where func.id=? order by para.id";
		List<Map<String, Object>> allFunctionParameters = dataSource.queryForList(sql, functionDBId);
		for (Map<String, Object> oneFunctionPara : allFunctionParameters) {
			PersistFunctionParameter parameter = new PersistFunctionParameter(oneFunctionPara);
			parameters.add(parameter);
		}
		return parameters;
	}

	@Override
	public boolean saveFunctionPramaters(int functionDBId,
			List<PersistFunctionParameter> parameters) throws EisSysException {
		if (parameters == null || parameters.size() == 0) return false; 
		String checkFuncSql = "select count(id) from tb_function where id=?";
		int funcCount = dataSource.queryForInt(checkFuncSql, functionDBId);
		if (funcCount > 0) {
			List<PersistFunctionParameter> originalParameters = getFunctionPramaters(functionDBId);
			
			Map<Integer, PersistFunctionParameter> originalMap = new HashMap<Integer, PersistFunctionParameter>();
			for (PersistFunctionParameter p : originalParameters) {
				originalMap.put(p.getId(), p);
			}
			
			List<PersistFunctionParameter> updateList = new ArrayList<PersistFunctionParameter>();
			List<PersistFunctionParameter> insertList = new ArrayList<PersistFunctionParameter>();
			List<PersistFunctionParameter> deleteList = new ArrayList<PersistFunctionParameter>();
			for (PersistFunctionParameter p : parameters) {
				if (p.getId() == 0) {
					super.preInsert(p);
					insertList.add(p);
				} else {
					if (originalMap.get(p.getId()) != null) {
						super.preUpdate(p);
						if (p.getDeleted() == 0) updateList.add(p);
						else deleteList.add(p);
					}
				}
			}
			
			if (deleteList.size() > 0) {
				StringBuilder deleteSql = new StringBuilder("delete from tb_functionparameter where id in(");
				for (int i = 0; i < deleteList.size(); i++) {
					deleteSql.append(deleteList.get(i).getId());
					if (i < deleteList.size() - 1) {
						deleteSql.append(",");
					}
				}
				deleteSql.append(")");
				try {
					dataSource.update(deleteSql.toString());
				} catch (Throwable t) {
					logger.error("Exception met when delete function parameter", t);
				}
			}
			
			if (updateList.size() > 0) {
				String updateSql = "update tb_functionparameter set functionDBID=?,parameterXml=?,updateDate=?,updatedBy=? where id=?";
				
				try {
					dataSource.batchUpdate(updateSql, new FunctionParameterBatchSetter(updateList));
				} catch (Throwable t) {
					logger.error("Exception met when update function parameter", t);
				}
			}
			
			if (insertList.size() > 0) {
				String insertSql = "insert into tb_functionparameter (functionDBID,parameterXml,createDate,createBy) values (?,?,?,?)";
				
				try {
					dataSource.batchUpdate(insertSql, new FunctionParameterBatchSetter(insertList));
				} catch (Throwable t) {
					logger.error("Exception met when insert function parameter", t);
				}
			}
			return true;
		} else {
			throw new EisSysException(EisErrorCode.saveParameterFuncNotExist);
		}
	}
}
